﻿using System.Windows.Input;
using System.Windows;
using System.Windows.Media;

namespace Super.Hmi.Behavior
{
    /// <summary>
    /// Element 事件
    /// </summary>
    public class ElementBehavior
    {
        // 存储每个窗口的事件处理程序
        private static readonly Dictionary<Window, MouseButtonEventHandler> _windowHandlers = new Dictionary<Window, MouseButtonEventHandler>();
        #region IsCloseCommandEnabled 属性
        public static bool GetIsCloseCommandEnabled(DependencyObject obj) => (bool)obj.GetValue(IsCloseCommandEnabledProperty);
        public static void SetIsCloseCommandEnabled(DependencyObject obj, bool value) => obj.SetValue(IsCloseCommandEnabledProperty, value);
        public static readonly DependencyProperty IsCloseCommandEnabledProperty = DependencyProperty.RegisterAttached("IsCloseCommandEnabled", typeof(bool), typeof(ElementBehavior), new PropertyMetadata(false, OnIsCloseCommandEnabledChanged));
        #endregion
        #region CloseCommand 属性
        public static ICommand GetCloseCommand(DependencyObject obj) => (ICommand)obj.GetValue(CloseCommandProperty);
        public static void SetCloseCommand(DependencyObject obj, ICommand value) => obj.SetValue(CloseCommandProperty, value);
        public static readonly DependencyProperty CloseCommandProperty = DependencyProperty.RegisterAttached("CloseCommand", typeof(ICommand), typeof(ElementBehavior));
        #endregion
        #region CloseCommandParameter 属性 
        public static object GetCloseCommandParameter(DependencyObject obj) => obj.GetValue(CloseCommandParameterProperty);
        public static void SetCloseCommandParameter(DependencyObject obj, object value) => obj.SetValue(CloseCommandParameterProperty, value);
        public static readonly DependencyProperty CloseCommandParameterProperty = DependencyProperty.RegisterAttached("CloseCommandParameter", typeof(object), typeof(ElementBehavior));
        #endregion
        private static void OnIsCloseCommandEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (d is FrameworkElement element)
            {
                element.Unloaded -= ElementUnloaded;
                element.Loaded -= ElementLoaded;
                if ((bool)e.NewValue)
                {
                    element.Loaded += ElementLoaded;
                    element.Unloaded += ElementUnloaded;
                }
            }
        }
        private static void ElementLoaded(object sender, RoutedEventArgs e)
        {
            var element = (FrameworkElement)sender;
            var window = Window.GetWindow(element);
            if (window == null) return;

            // 如果已为该窗口添加过处理程序，则跳过
            if (_windowHandlers.ContainsKey(window)) return;
            // 创建新的处理程序
            MouseButtonEventHandler handler = (s, args) =>
            {
                // 检查点击是否在元素外部
                if (element.Visibility == Visibility.Visible && !element.IsMouseOver && !IsChildMouseOver(element, args))
                {
                    // 执行关闭命令
                    var closeCommand = GetCloseCommand(element);
                    var closeCommandParameter = GetCloseCommandParameter(element);
                    if (closeCommand?.CanExecute(closeCommandParameter ?? null) == true)
                        closeCommand.Execute(closeCommandParameter);
                }
            };
            // 订阅事件
            window.PreviewMouseDown += handler;
            // 存储处理程序以便后续移除
            _windowHandlers[window] = handler;
        }
        private static void ElementUnloaded(object sender, RoutedEventArgs e)
        {
            var element = (FrameworkElement)sender;
            var window = Window.GetWindow(element);
            if (window == null) return;

            // 移除事件处理程序
            if (_windowHandlers.TryGetValue(window, out var handler))
            {
                window.PreviewMouseDown -= handler;
                _windowHandlers.Remove(window);
            }
        }
        private static bool IsChildMouseOver(FrameworkElement parent, MouseButtonEventArgs e)
        {
            var hit = VisualTreeHelper.HitTest(parent, e.GetPosition(parent));
            return hit?.VisualHit != null && parent.IsAncestorOf(hit.VisualHit);
        }
    }
}
